<?php

/**
 * Simple Machines Forum (SMF) 
 *
 * @package testsuite
 * @author Simple Machines
 * @copyright 2011 Simple Machines
 * @license http://www.simplemachines.org/about/smf/license.php BSD
 *
 * @version 2.0
 */

if (!defined('SMF'))
	die ('Hacking Attempt...');

function TS_SMTestSuiteMain()
{
	global $context, $txt, $scripturl, $sourcedir, $settings;

	// Naughty, naughty are we?
	TS_can_do('view_all');
	
	$default_action_func = 'TS_ShowProjectList';

	// Call CSS :P, which we have made with utmost love.
	$context['html_headers'] .= '<link rel="stylesheet" type="text/css" href="' . $settings['default_theme_url'] .  '/css/SM-TestSuite.css" />';

	// Load our template & language file.
	loadTemplate('SM-TestSuite');
	loadLanguage('SM-TestSuite');

	$context['test_suite'] = array();
	$context['test_suite']['debug'] = 1;
	$context['test_suite']['url'] = $scripturl . '?action=testsuite';
	
	// Add a link to the Christmas tree!
	$context['linktree'][] = array(
		'url' => $context['test_suite']['url'],
		'name' => $txt['sm_testsuite_link'],
	);
	
	$context['test_suite']['perms'] = TS_load_permissions();
	
	// Set the IDs we will be using, if they are available.
	$context['test_suite']['current_project'] = isset($_REQUEST['project']) ? (int) $_REQUEST['project'] : 0;
	$context['test_suite']['current_suite'] = isset($_REQUEST['suite']) ? (int) $_REQUEST['suite'] : 0;
	$context['test_suite']['current_case'] = isset($_REQUEST['case']) ? (int) $_REQUEST['case'] : 0;
	$context['test_suite']['current_run'] = isset($_REQUEST['run']) ? (int) $_REQUEST['run'] : 0;

	$subActions = array(
//		Main views.
		'project' => 'TS_ShowCurrentProject',
		'suite' => 'TS_ShowCurrentSuite',
		'case' => 'TS_ShowCurrentCase',
		'runsforsuite' => 'TS_RunList',
//		Project related.
		'createproject' => 'TS_Project',
		'createproject2' => 'TS_Project2',
		'editproject' => 'TS_EditProject',
		'editproject2' => 'TS_EditProject2',
		'removeproject' => 'TS_DeleteItem',
//		Suite related.
		'editsuite' => 'TS_EditProject',
		'createsuite' => 'TS_Project',
		'removesuite' => 'TS_DeleteItem',
//		Case related.
		'createCase' => 'TS_Cases',
		'createCase2' => 'TS_Cases2',
		'editcase' => 'TS_EditCase',
		'editcase2' => 'TS_EditCase2',
		'removecase' => 'TS_DeleteItem',
//		Run related.
 		'createrun' => 'TS_PostRun',
 		'createrun2' => 'TS_PostRun2',
		'editrun' => 'TS_EditRun',
		'editrun2' => 'TS_EditRun2',
		'removerun' => 'TS_DeleteItem',
	);

	foreach ($subActions as $key => $action)
	{
		if (isset($_REQUEST[$key]))
		{
			if (function_exists($subActions[$key]))
				return $subActions[$key]();
		}
	}

	// At this point we can just do our default.
	$default_action_func();
}

function TS_ShowProjectList()
{
	global $context, $sourcedir, $txt;
	// Define a page title...
	$context['page_title'] = $txt['sm_testsuite'];

	// Show off our projects how about it?
	require_once($sourcedir . '/Subs-SM-TestSuite.php');
	$context['test_suite']['projects'] = TS_requestProjects();	
}

function TS_ShowCurrentProject()
{
	global $scripturl, $context, $sourcedir;

	// Load our info! It's trustworthy, trust us.
	require_once($sourcedir . '/Subs-SM-TestSuite.php');
	$context['test_suite']['project'] = TS_loadProject($context['test_suite']['current_project']);
	
	$context['sub_template'] = 'sm_testsuite_project_view';

	// Make a note of Project ID and build a linktree for Project
	$context['linktree'][] = array(
		'url' => $context['test_suite']['url'] . ';project=' . $context['test_suite']['current_project'],
		'name' => $context['test_suite']['project']['name'],
	);
	$context['page_title'] = $context['test_suite']['project']['name'];
}

function TS_ShowCurrentSuite()
{
	global $scripturl, $context, $sourcedir;

	// The heart and gold of our magic.
	require_once($sourcedir . '/Subs-SM-TestSuite.php');
	$context['test_suite']['suite'] = TS_loadSuite($context['test_suite']['current_suite']);
	
	$context['sub_template'] = 'sm_testsuite_case_view';
	$context['page_title'] = $context['test_suite']['suite']['name'];
	
	// Add the project the suite belongs to to the linktree.
	$context['linktree'][] = array(
		'url' => $context['test_suite']['url'] . ';project=' . $context['test_suite']['suite']['id_project'],
		'name' => $context['test_suite']['suite']['project_name'],
	);
	// Add the current suite to the linktree.
	$context['linktree'][] = array(
		'url' => $context['test_suite']['url'] . ';suite=' . $context['test_suite']['current_suite'],
		'name' => $context['test_suite']['suite']['name'],
	);
}

function TS_ShowCurrentCase()
{
	global $scripturl, $context, $sourcedir;

	// Load the case for the template to have its way with.
	require_once($sourcedir . '/Subs-SM-TestSuite.php');
	$context['test_suite']['case'] = TS_loadCase($context['test_suite']['current_case']);
	
	$context['page_title'] = $context['test_suite']['case']['name'];
	$context['linktree'][] = array(
		'url' => $context['test_suite']['url'] . ';project=' . $context['test_suite']['case']['id_project'],
		'name' => $context['test_suite']['case']['project_name'],
	);
	$context['linktree'][] = array(
		'url' => $context['test_suite']['url'] . ';suite=' . $context['test_suite']['case']['id_suite'],
		'name' => $context['test_suite']['case']['suite_name'],
	);
	$context['linktree'][] = array(
		'url' => $context['test_suite']['url'] . ';case=' . $context['test_suite']['current_case'],
		'name' => $context['test_suite']['case']['name'],
	);
	$context['sub_template'] = 'sm_testsuite_separate_case_view';
}

function TS_RunList()
{
	global $scripturl, $context, $txt;

	$context['test_suite']['current_suite'] = isset($_REQUEST['runsforsuite']) ? (int) $_REQUEST['runsforsuite'] : 0;
	$context['test_suite']['result'] = isset($_REQUEST['result']) ? strtolower($_REQUEST['result']) : '';

	require_once($sourcedir . '/Subs-SM-TestSuite.php');
	TS_requestRunsforSuites();
	$context['test_suite']['suite'] = TS_loadSuite($context['test_suite']['current_suite']);

	$context['page_title'] = $txt['ts_runs_for_suites'];
	$context['linktree'][] = array(
		'url' => $scripturl . '?action=testsuite;project=' . $context['test_suite']['suite']['id_project'],
		'name' => $context['test_suite']['suite']['project_name'],
	);
	$context['sub_template'] = 'sm_testsuite_count_link';
}

//creation of world (Projects and Suites):P
function TS_Project()
{
	global $txt, $scripturl, $modSettings, $user_info, $context, $sourcedir, $smcFunc, $settings;
	
	isAllowedTo('ts_post_projects');
	
	// Get Project ID For suites
	$context['test_suite']['current_project'] = isset($_REQUEST['proj']) ? (int) $_REQUEST['proj'] : 0;
	$project_id = $context['test_suite']['current_project'];
	$suite_id = $context['test_suite']['current_suite'];

	if (empty($context['post_errors']))
	    $context['post_errors'] = array();

	TS_ProjectValidator();
	
	// Set the destination action for submission.
	$context['destination'] = 'createProject2';
	$context['submit_label'] = $txt['create'];

	if (empty($project_id))
	{
	    $context['page_title'] = $txt['start_new_project'];
	}
	
	else
	{
	    $context['page_title'] = $txt['start_new_suite'];
	}

	// Call Our Sub-Template.
	$context['sub_template'] = 'create_project';
	
	// Add a link to the Christmas tree!
	if(empty($project_id))
	{
		$context['linktree'][] = array(
		    'name' => '<em>' . $txt['create_project'] . '</em>',
		);
	}
	
	else
	{
	    $context['linktree'][] = array(
		    'url' => $scripturl . '?action=testsuite;project='. $project_id,
		    'name' => $txt['project'],
		    'extra_before' => '<span' . ($settings['linktree_inline'] ? 
				' class="smalltext"' : '') . '><strong class="nav">' . $context['page_title'] . ' ( </strong></span>',
		    'extra_after' => '<span' . ($settings['linktree_inline'] ?
				' class="smalltext"' : '') . '><strong class="nav"> )</strong></span>'
	    );
	}
}

function TS_Project2()
{
	global $txt, $modSettings, $sourcedir, $context, $scripturl, $user_info, $smcFunc;

	isAllowedTo('ts_post_projects');
	
	require_once($sourcedir . '/Subs-SM-TestSuite.php');

	// Sneaking off, are we?
	if (empty($_POST))
		redirectexit($scripturl);

	// Get Project ID For suites
	$context['test_suite']['current_project'] = isset($_REQUEST['proj']) ? (int) $_REQUEST['proj'] : 0; 
	$project_id = $context['test_suite']['current_project'];

	// Prevent double submission of this form.
	checkSubmitOnce('check');

	// No errors as yet.
	$post_errors = array();

	// If the session has timed out, let the user re-submit their form.
	if (checkSession('project', '', false) != '')
		$post_errors[] = 'session_timeout';

	// Check the name and description coming.
	if (!isset($_POST['name']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['name'])) === '')
		$post_errors[] = 'no_name';
	if (!isset($_POST['description']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['description']), ENT_QUOTES) === '')
		$post_errors[] = 'no_description';
	elseif (!empty($modSettings['max_messageLength']) && $smcFunc['strlen']($_POST['description']) > $modSettings['max_messageLength'])
		$post_errors[] = 'long_description';
	else
	{
		// Prepare the description a bit for some additional testing.
		$_POST['description'] = $smcFunc['htmlspecialchars']($_POST['description'], ENT_QUOTES);
	}

	// Any mistakes?
	if (!empty($post_errors))
	{
		loadLanguage('Errors');
		
		$context['post_error'] = array('description' => array());
		foreach ($post_errors as $post_error)
		{
			$context['post_error'][$post_error] = true;
			if ($post_error == 'long_description')
				$txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);

			$context['post_error']['description'][] = $txt['error_' . $post_error];
		}

		return TS_Project();
	}

	// At about this point, we're creating and that's that.
	ignore_user_abort(true);
	@set_time_limit(300);

	// Add special html entities to the Project Name, username and email.
	$_POST['name'] = strtr($smcFunc['htmlspecialchars']($_POST['name']), array("\r" => '', "\n" => '', "\t" => ''));
	$poster_name = htmlspecialchars($user_info['username']);
	$poster_email = htmlspecialchars($user_info['email']);

	// At this point, we want to make sure the Project Name isn't too long.
	if ($smcFunc['strlen']($_POST['name']) > 100)
		$_POST['name'] = $smcFunc['substr']($_POST['name'], 0, 100);

	// Collect all parameters for the creation of Project.
	if (empty($project_id))
	{
		$projectOption = array(
			'id' => empty($project_id) ? 0 : $project_id,
			'project_name' => $_POST['name'],
			'description' => $_POST['description'],
		);
		$posterOptions = array(
			'id' => $user_info['id'],
			'name' => $poster_name,
			'email' => $poster_email,
		);
		
		TS_createProject($projectOption, $posterOptions);

		// Dut-dut-duh-duh-DUH-duh-dut-duh-duh!  *dances to the Final Fantasy Fanfare...*
		redirectexit('action=testsuite');
	}
	
	// Collect all parameters for the creation of Suite.
	else if (!empty($project_id))
	{
		$suiteOptions = array(
			'id' => empty($suite_id) ? 0 : $suite_id,
			'id_project' => empty($project_id) ? 0 : $project_id,
			'suite_name' => $_POST['name'],
			'description' => $_POST['description'],
		);
		$posterOptions = array(
			'id' => $user_info['id'],
			'name' => $poster_name,
			'email' => $poster_email,
		);
		
		TS_createSuite($suiteOptions, $posterOptions);

		// Dut-dut-duh-duh-DUH-duh-dut-duh-duh!  *dances to the Final Fantasy Fanfare...*
		redirectexit('action=testsuite;project=' . $project_id);
	}
}

function TS_EditProject()
{
	global $txt, $scripturl, $modSettings, $user_info, $context, $sourcedir, $smcFunc, $settings;

	// Editing projects just consists of title/description so no need now for separate permission really.
	isAllowedTo('ts_post_project');
	
	if (empty($context['test_suite']['current_project']))
	$context['test_suite']['current_project'] = isset($_REQUEST['editproject']) ? (int) $_REQUEST['editproject'] : 0;
	$project_id = $context['test_suite']['current_project'];
	
	if (empty ($project_id))
	$project_id = isset($_REQUEST['proj']) ? (int) $_REQUEST['proj'] : 0;
	
	if (empty($context['test_suite']['current_suite']))
	$context['test_suite']['current_suite'] = isset($_REQUEST['editsuite']) ? (int) $_REQUEST['editsuite'] : 0;
	$suite_id = $context['test_suite']['current_suite'];
	if (empty ($suite_id))
	$suite_id = isset($_REQUEST['s']) ? (int) $_REQUEST['s'] : 0;
	
	if(empty($project_id) && empty($suite_id))
	return false;

	require_once($sourcedir . '/Subs-SM-TestSuite.php');

	// Get data for this specific suite.
	if(!empty($suite_id))
	{
		$request = $smcFunc['db_query']('', '
				SELECT
					id_project, suite_name, description, id_member, poster_name, poster_time, poster_email, modified_by, modified_time
					FROM {db_prefix}testsuite_suites
					WHERE id_suite = {int:current_suite}',
					array(
					'current_suite' => $suite_id,
					'current_member' => $user_info['id'],
				)
			);
			
		if ($smcFunc['db_num_rows']($request) == 0)
			fatal_lang_error('no_suite', false);
		$row = $smcFunc['db_fetch_assoc']($request);
		$smcFunc['db_free_result']($request);

		$context['name'] = $row['suite_name'];
		$context['description'] = $row['description'];
		$context['test_suite']['current_project'] = $row['id_project'];

		$context['test_suite']['suite'] = array(
		    'name' => $row['suite_name'],
		    'description' => $row['description'],
		);
	}
	
	// Get data for the project to be edited.
	else
	{
		$request = $smcFunc['db_query']('', '
			SELECT
				project_name, description, id_member, poster_name, poster_time, poster_email, modified_by, modified_time
				FROM {db_prefix}testsuite_projects
				WHERE id_project = {int:current_project}',
				array(
				'current_project' => $project_id,
				'current_member' => $user_info['id'],
			)
		);
		
		if ($smcFunc['db_num_rows']($request) == 0)
			fatal_lang_error('no_project', false);
		$row = $smcFunc['db_fetch_assoc']($request);
		$smcFunc['db_free_result']($request);

		$context['name'] = $row['project_name'];
		$context['description'] = $row['description'];

		$context['test_suite']['project'] = array(
		    'name' => $row['project_name'],
		    'description' => $row['description'],
		);
	}
	
	if (empty($context['post_errors']))
	    $context['post_errors'] = array();
		
	TS_ProjectValidator();

	// Set the destination action for submission.
	$context['destination'] = 'editproject2';
	$context['submit_label'] = $txt['submit'];

	// Call Our Sub-Template.
	$context['sub_template'] = 'edit_project';

	if(!empty($suite_id))
	    $context['page_title'] = $txt['edit'] . ' '. $txt['suite'];
	else
	    $context['page_title'] = $txt['edit'] . ' '. $txt['project'];
	
	if (!empty($suite_id))
	{
	    $context['linktree'][] = array(
		'url' => $scripturl . '?action=testsuite;project='. $context['test_suite']['current_project'],
		'name' => $txt['project'],
		);
		
		$context['linktree'][] = array(
		'url' => $context['test_suite']['url'] . ';suite='. $suite_id,
		'name' => $context['test_suite']['suite']['name'],
		'extra_before' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><strong class="nav">' . $context['page_title'] . ' ( </strong></span>',
		'extra_after' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><strong class="nav"> )</strong></span>'
		);
	}
	
	else
	{
	    $context['linktree'][] = array(
		'url' => $context['test_suite']['url'] . ';project=' . $project_id,
		'name' => $context['test_suite']['project']['name'],
		'extra_before' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><strong class="nav">' . $context['page_title'] . ' ( </strong></span>',
		'extra_after' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><strong class="nav"> )</strong></span>'
	    );
	}
}

function TS_EditProject2()
{
	global $txt, $modSettings, $sourcedir, $context, $scripturl, $user_info, $smcFunc;

	isAllowedTo('ts_post_project');
	
	require_once($sourcedir . '/Subs-SM-TestSuite.php');

	// Coming from the suite...
	// !!! Note: This method makes it easy to spoof a project/suite ID.
	// A proper permission check should be added when permissions are added to make
	//	    sure that the user has permission to edit the current suite/project (if needed).
	$project_id = $context['test_suite']['current_project'];
	if (empty ($project_id))
	    $project_id = isset($_REQUEST['proj']) ? (int) $_REQUEST['proj'] : 0;

	$suite_id = $context['test_suite']['current_suite'];
	if (empty ($suite_id))
	$suite_id = isset($_REQUEST['s']) ? (int) $_REQUEST['s'] : 0;

	// Prevent double submission of this form.
	checkSubmitOnce('check');

	// No errors as yet.
	$post_errors = array();

	// If the session has timed out, let the user re-submit their form.
	if (checkSession('editproject', '', false) != '')
		$post_errors[] = 'session_timeout';

	// Get data for this specific suite.
	if(!empty($suite_id))
	{
		$request = $smcFunc['db_query']('', '
				SELECT
					suite_name, description, id_member, poster_name, poster_time, poster_email, modified_by, modified_time
					FROM {db_prefix}testsuite_suites
					WHERE id_suite = {int:current_suite}',
					array(
					'current_suite' => $suite_id,
					'current_member' => $user_info['id'],
				)
			);
			
		if ($smcFunc['db_num_rows']($request) == 0)
			fatal_lang_error('no_suite', false);
		$row = $smcFunc['db_fetch_assoc']($request);
		$smcFunc['db_free_result']($request);
	}

	// !!! Call TS_loadProject(current_project, false) here instead.
	// Get data for the project to be edited.
	else
	{
		$request = $smcFunc['db_query']('', '
			SELECT
				project_name, description, id_member, poster_name, poster_time, poster_email, modified_by, modified_time
				FROM {db_prefix}testsuite_projects
				WHERE id_project = {int:current_project}',
				array(
				'current_project' => $project_id,
				'current_member' => $user_info['id'],
			)
		);
		
		if ($smcFunc['db_num_rows']($request) == 0)
			fatal_lang_error('no_project', false);
		$row = $smcFunc['db_fetch_assoc']($request);
		$smcFunc['db_free_result']($request);
	}
		
		
	// Check the name and description coming.
	if (!isset($_POST['name']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['name'])) === '')
		$post_errors[] = 'no_name';
	if (!isset($_POST['description']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['description']), ENT_QUOTES) === '')
		$post_errors[] = 'no_description';
	elseif (!empty($modSettings['max_messageLength']) && $smcFunc['strlen']($_POST['description']) > $modSettings['max_messageLength'])
		$post_errors[] = 'long_description';
	else
	{
		// Prepare the description a bit for some additional testing.
		$_POST['description'] = $smcFunc['htmlspecialchars']($_POST['description'], ENT_QUOTES);
	}

	// Any mistakes?
	if (!empty($post_errors))
	{
		loadLanguage('Errors');
		
		$context['post_error'] = array('description' => array());
		foreach ($post_errors as $post_error)
		{
			$context['post_error'][$post_error] = true;
			if ($post_error == 'long_description')
				$txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);

			$context['post_error']['description'][] = $txt['error_' . $post_error];
		}
		$context['test_suite']['current_project'] = $project_id;
		$context['test_suite']['current_suite'] = $suite_id;
		return TS_EditProject();
	}

	// At about this point, we're creating and that's that.
	ignore_user_abort(true);
	@set_time_limit(300);

	// Add special html entities to the Project Name, username and email.
	$_POST['name'] = strtr($smcFunc['htmlspecialchars']($_POST['name']), array("\r" => '', "\n" => '', "\t" => ''));
	$poster_name = htmlspecialchars($user_info['username']);
	$poster_email = htmlspecialchars($user_info['email']);

	// At this point, we want to make sure the Project Name isn't too long.
	if ($smcFunc['strlen']($_POST['name']) > 100)
		$_POST['name'] = $smcFunc['substr']($_POST['name'], 0, 100);

	if(!empty($suite_id))
	{
		$suiteOptions = array(
			'id' => empty($suite_id) ? 0 : $suite_id,
			'id_project' => empty($project_id) ? 0 : $project_id,
			'suite_name' => $_POST['name'],
			'description' => $_POST['description'],
		);
		$posterOptions = array();

		// Only consider marking as editing if they have edited the subject, message or icon.
		if ((isset($_POST['name']) && $_POST['name'] != $row['suite_name']) || (isset($_POST['description']) && $_POST['description'] != $row['description']))
		{
				$suiteOptions['modify_time'] = time();
				$suiteOptions['modified_by'] = $user_info['name'];
		}
		TS_modifySuite($suiteOptions, $posterOptions);

		// If we didn't change anything this time but had before put back the old info.
		if (!isset($suiteOptions['modify_time']) && !empty($row['modified_time']))
		{
			$suiteOptions['modify_time'] = $row['modified_time'];
			$suiteOptions['modified_by'] = $row['modified_by'];
		}
		redirectexit('action=testsuite;project='. $project_id);
	}
	
	elseif (!empty($project_id))
	{
		$projectOptions = array(
			'id' => empty($project_id) ? 0 : $project_id,
			'project_name' => $_POST['name'],
			'description' => $_POST['description'],
		);
		$posterOptions = array();

		// Only consider marking as editing if they have edited the subject, message or icon.
		if ((isset($_POST['name']) && $_POST['name'] != $row['project_name']) || (isset($_POST['description']) && $_POST['description'] != $row['description']))
		{
				$projectOptions['modify_time'] = time();
				$projectOptions['modified_by'] = $user_info['name'];
		}
		TS_modifyProject($projectOptions, $posterOptions);

		// If we didn't change anything this time but had before put back the old info.
		if (!isset($projectOptions['modify_time']) && !empty($row['modified_time']))
		{
			$projectOptions['modify_time'] = $row['modified_time'];
			$projectOptions['modified_by'] = $row['modified_by'];
		}
		redirectexit('action=testsuite');
	}
}

function TS_ProjectValidator()
{
	global $context, $modSettings, $smcFunc, $txt;

	//Creating?
	if (isset($_POST['description']) || !empty($context['post_error']))
	{
		// Validate inputs.
		if (empty($context['post_error']))
		{
			if (htmltrim__recursive(htmlspecialchars__recursive($_POST['name'])) == '')
				$context['post_error']['no_name'] = true;
			if (htmltrim__recursive(htmlspecialchars__recursive($_POST['description'])) == '')
				$context['post_error']['no_description'] = true;
			if (!empty($modSettings['max_messageLength']) && $smcFunc['strlen']($_POST['description']) > $modSettings['max_messageLength'])
				$context['post_error']['long_description'] = true;
		}
		else
		{
			if (!isset($_POST['name']))
				$_POST['name'] = '';
			if (!isset($_POST['description']))
				$_POST['description'] = '';
		}

		// Set up the inputs for the form.
		$name = strtr($smcFunc['htmlspecialchars']($_POST['name']), array("\r" => '', "\n" => '', "\t" => ''));
		$project_description = $smcFunc['htmlspecialchars']($_POST['description'], ENT_QUOTES);

		// Make sure the subject isn't too long - taking into account special characters.
		if ($smcFunc['strlen']($name) > 100)
			$name = $smcFunc['substr']($name, 0, 100);

		// Have we inadvertently trimmed off the subject of useful information?
		if ($smcFunc['htmltrim']($name) === '')
			$context['post_error']['no_name'] = true;

		// Any errors occurred?
		if (!empty($context['post_error']))
		{
			loadLanguage('Errors');

			$context['error_type'] = 'minor';

			$context['post_error']['description'] = array();
			foreach ($context['post_error'] as $post_error => $dummy)
			{
				if ($post_error == 'description')
					continue;

				if ($post_error == 'long_description')
					$txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);

				$context['post_error']['description'][] = $txt['error_' . $post_error];

				$context['error_type'] = 'serious';
			}
		}
		$context['name'] = addcslashes($name, '"');
		$context['description'] = str_replace(array('"', '<', '>', '&nbsp;'), array('&quot;', '&lt;', '&gt;', ' '), $project_description);

		checkSubmitOnce('register');
	}
}

// Ok complete new functions to create Test Cases and Runs
function TS_Cases()
{
	global $txt, $scripturl, $modSettings, $user_info, $context, $sourcedir, $smcFunc, $settings;
	
	if (empty($context['post_errors']))
		$context['post_errors'] = array();
	
	$context['test_suite']['current_suite'] = isset($_REQUEST['s']) ? (int) $_REQUEST['s'] : 0;
	$suite_id = $context['test_suite']['current_suite'];
	
	if(!empty($_REQUEST['id_assigned']))
	{
            $id_assigned = (int) $_REQUEST['id_assigned'];
	}
	
	TS_CaseValidator();
	
	// Set the destination action for submission.
	$context['destination'] = 'createCase2';
	$context['submit_label'] = $txt['create'];
	
	// Create page titles and linktrees
	$context['page_title'] = $txt['start_new_case'];
	
	$context['linktree'][] = array(
	'url' => $context['test_suite']['url'] . ';suite='. $suite_id,
	'name' => $txt['suite'],
	'extra_before' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><strong class="nav">' . $context['page_title'] . ' ( </strong></span>',
	'extra_after' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><strong class="nav"> )</strong></span>'
	);
	
	// Make some more effort for BBC Codes used in Test Cases
	$context['use_smileys'] = true;
	$context['sub_template'] = 'create_case';
	
	require_once($sourcedir . '/Subs-SM-TestSuite.php');

	// Now create the editor for description.
	$editorOptions = array(
		'id' => 'message',
		'value' => $context['message'],
		'height' => '150px',
		'width' => '80%',
	);
	TS_editor_controller($editorOptions);
	
	// For steps.
	$editorOptions = array(
		'id' => 'steps',
		'value' => $context['steps'],
		'height' => '150px',
		'width' => '80%',
	);
	TS_editor_controller($editorOptions);
	
	// For Expected Result.
	$editorOptions = array(
		'id' => 'expected_result',
		'value' => $context['expected_result'],
		'height' => '150px',
		'width' => '80%',
	);
	TS_editor_controller($editorOptions);
}

function TS_Cases2()
{
	global $txt, $modSettings, $sourcedir, $context, $scripturl, $user_info, $smcFunc;

	require_once($sourcedir . '/Subs-SM-TestSuite.php');
	require_once($sourcedir . '/Subs-Post.php');

	$suite_id = isset($_REQUEST['s']) ? (int) $_REQUEST['s'] : 0;
	$id_case = isset($_REQUEST['c']) ? (int) $_REQUEST['c'] : 0;
	$id_assigned = isset($_REQUEST['id_assigned']) ? (int) $_REQUEST['id_assigned'] : 0; 

	// Prevent double submission of this form.
	checkSubmitOnce('check');

	// No errors as yet.
	$post_errors = array();

	// If the session has timed out, let the user re-submit their form.
	if (checkSession('cases', '', false) != '')
		$post_errors[] = 'session_timeout';

	// Check the name and message and steps for Cases.
	if (!isset($_POST['name']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['name'])) === '')
		$post_errors[] = 'no_name';
	if (!isset($_POST['message']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['message']), ENT_QUOTES) === '')
		$post_errors[] = 'no_message';
	if (!isset($_POST['steps']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['steps']), ENT_QUOTES) === '')
		$post_errors[] = 'no_steps';
	if (!isset($_POST['expected_result']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['expected_result']), ENT_QUOTES) === '')
		$post_errors[] = 'no_expected_result';
	if (!empty($modSettings['max_messageLength']) && ($smcFunc['strlen']($_REQUEST['message']) > $modSettings['max_messageLength'] || $smcFunc['strlen']($_REQUEST['steps']) > $modSettings['max_messageLength'] || $smcFunc['strlen']($_REQUEST['expected_result']) > $modSettings['max_messageLength']))
		$post_errors[] = 'long_message';
	else
	{
		// Prepare the message and steps a bit for some additional testing.
		$_POST['message'] = $smcFunc['htmlspecialchars']($_POST['message'], ENT_QUOTES);
		$_POST['steps'] = $smcFunc['htmlspecialchars']($_POST['steps'], ENT_QUOTES);
		$_POST['expected_result'] = $smcFunc['htmlspecialchars']($_POST['expected_result'], ENT_QUOTES);
		
		// Let's see if there's still some content left without the tags.
		if ($smcFunc['htmltrim'](strip_tags(parse_bbc($_POST['message'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['message'], '[html]') === false))
			$post_errors[] = 'no_message';
		if ($smcFunc['htmltrim'](strip_tags(parse_bbc($_POST['steps'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['steps'], '[html]') === false))
			$post_errors[] = 'no_steps';
		if ($smcFunc['htmltrim'](strip_tags(parse_bbc($_POST['expected_result'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['expected_result'], '[html]') === false))
			$post_errors[] = 'no_expected_result';
	}

	// Any mistakes?
	if (!empty($post_errors))
	{
		loadLanguage('Errors');
		
		//Check message from cases
		$context['post_error'] = array('message' => array());
		foreach ($post_errors as $post_error)
		{
			$context['post_error'][$post_error] = true;
			if ($post_error == 'long_message')
				$txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);

			$context['post_error']['message'][] = $txt['error_' . $post_error];
		}
		return TS_Cases();
	}

	// At about this point, we're posting and that's that.
	ignore_user_abort(true);
	@set_time_limit(300);

	// Add special html entities to the Test Case Name, username, email and expected result.
	$_POST['name'] = strtr($smcFunc['htmlspecialchars']($_POST['name']), array("\r" => '', "\n" => '', "\t" => ''));
	$poster_name = htmlspecialchars($user_info['username']);
	$poster_email = htmlspecialchars($user_info['email']);

	// At this point, we want to make sure the name isn't too long.
	if ($smcFunc['strlen']($_POST['name']) > 100)
		$_POST['name'] = $smcFunc['substr']($_POST['name'], 0, 100);
	
	// Collect all parameters for the creation of Test Cases.
	$caseOption = array(
		'id' => empty($case_id) ? 0 : $case_id,
		'id_suite' => empty($suite_id) ? 0 : $suite_id,
		'case_name' => $_POST['name'],
		'description' => $_POST['message'],
		'steps' => $_POST['steps'],
		'expected_result' => $_POST['expected_result'],
	);
	$posterOptions = array(
		'id' => $user_info['id'],
		'name' => $poster_name,
		'email' => $poster_email,
		'id_assigned' =>  empty($id_assigned) ? 0 : $id_assigned,
	);
	TS_createCase($caseOption, $posterOptions);

	// Dut-dut-duh-duh-DUH-duh-dut-duh-duh!  *dances to the Final Fantasy Fanfare...*
	redirectexit('action=testsuite;suite=' . $suite_id);
}

function TS_EditCase()
{
	global $txt, $scripturl, $modSettings, $user_info, $context, $sourcedir, $smcFunc, $settings;
	
	if (empty($context['test_suite']['current_case']))
		$context['test_suite']['current_case'] = isset($_REQUEST['editcase']) ? (int) $_REQUEST['editcase'] : 0; 
	$case_id = $context['test_suite']['current_case'];
	if (empty ($case_id))
	$case_id = isset($_REQUEST['c']) ? (int) $_REQUEST['c'] : 0;

	$id_assigned = isset($_REQUEST['id_assigned']) ? (int) $_REQUEST['id_assigned'] : 0; 

	if(empty($case_id))
		return false;

	require_once($sourcedir . '/Subs-SM-TestSuite.php');

	// Get data for this specific case. 
	// !!! Why aren't we using loadCase?
	$request = $smcFunc['db_query']('', '
			SELECT
				c.id_suite, s.id_project, c.case_name, c.description, c.steps, c.expected_result, c.id_member, c.poster_name, c.poster_time, c.poster_email, c.id_assigned, c.modified_by, c.modified_time
				FROM {db_prefix}testsuite_cases AS c
				INNER JOIN {db_prefix}testsuite_suites as s ON (s.id_suite = c.id_suite)
				WHERE c.id_case = {int:current_case}',
				array(
				'current_case' => $case_id,
				'current_member' => $user_info['id'],
			)
		);

	if ($smcFunc['db_num_rows']($request) == 0)
		fatal_lang_error('no_case', false);
	$row = $smcFunc['db_fetch_assoc']($request);
	$smcFunc['db_free_result']($request);

	// !!! Where is this used?
	$context['id_suite'] = $row['id_suite'];
	
	$context['test_suite']['current_suite'] = $row['id_suite'];
	$context['test_suite']['current_project'] = $row['id_project'];

	$context['test_suite']['current_project'] = $row['id_project'];
	$context['name'] = $row['case_name'];
	$context['message'] = $row['description'];
	$context['steps'] = $row['steps'];
	$context['expected_result'] = $row['expected_result'];
	$context['id_assigned'] = $row['id_assigned'];
	
	if (!($context['user']['is_admin'] || TS_can_do('manage_all') || TS_can_do('manage_project', $context['test_suite']['current_project']) || 
			TS_can_do('manage_suite', $context['test_suite']['current_suite'])))
	{
		fatal_lang_error($txt['ts_cannot_permission_generic']);
	}
		
	if (empty($context['post_errors']))
		$context['post_errors'] = array();
		
	TS_CaseValidator();

	// Set the destination action for submission.
	$context['destination'] = 'editcase2';
	$context['submit_label'] = $txt['submit'];

	$context['page_title'] = $txt['edit'] . ' '. $txt['case'];

	$context['linktree'][] = array(
	'url' => $context['test_suite']['url'] . 'suite=' . $context['id_suite'],
	'name' => $txt['suite'],
	);
	
	$context['linktree'][] = array(
	'url' => $context['test_suite']['url'] . ';case=' . $case_id,
	'name' => $context['name'],
	'extra_before' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><strong class="nav">' . $context['page_title'] . ' ( </strong></span>',
	'extra_after' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><strong class="nav"> )</strong></span>'
	);
	
	// Call Our Sub-Template.
	$context['sub_template'] = 'edit_case';
	
	// Make some more effort for BBC Codes used in Test Cases
	$context['use_smileys'] = true;

	// Now create the editor.
	$editorOptions = array(
		'id' => 'message',
		'value' => $context['message'],
		'height' => '150px',
		'width' => '80%',
	);
	TS_editor_controller($editorOptions);
	
	// Now create the editor.
	$editorOptions = array(
		'id' => 'steps',
		'value' => $context['steps'],
		'height' => '150px',
		'width' => '80%',
	);
	TS_editor_controller($editorOptions);
	
	// Now create the editor.
	$editorOptions = array(
		'id' => 'expected_result',
		'value' => $context['expected_result'],
		'height' => '150px',
		'width' => '80%',
	);
	TS_editor_controller($editorOptions);
}

function TS_EditCase2()
{
	global $txt, $modSettings, $sourcedir, $context, $scripturl, $user_info, $smcFunc;

	require_once($sourcedir . '/Subs-SM-TestSuite.php');
	require_once($sourcedir . '/Subs-Post.php');

	$case_id = $context['test_suite']['current_case'];
	if (empty ($case_id))
	$case_id = isset($_REQUEST['c']) ? (int) $_REQUEST['c'] : 0;
	
	$id_assigned = isset($_REQUEST['id_assigned']) ? (int) $_REQUEST['id_assigned'] : 0;

	// Prevent double submission of this form.
	checkSubmitOnce('check');

	// No errors as yet.
	$post_errors = array();

	// If the session has timed out, let the user re-submit their form.
	if (checkSession('editcase', '', false) != '')
		$post_errors[] = 'session_timeout';
	
	// !!! Incomplete, TBD.
	if (!($context['user']['is_admin'] || TS_can_do('manage_all')))
	{
		fatal_lang_error($txt['ts_cannot_permission_generic']);
	}

	if(!empty($case_id))
	{
		$request = $smcFunc['db_query']('', '
				SELECT
					c.case_name, c.description, c.steps, c.expected_result, c.id_member, c.poster_name, c.poster_time, c.poster_email, c.id_assigned, c.modified_by, c.modified_time
					FROM {db_prefix}testsuite_cases AS c
					WHERE c.id_case = {int:current_case}',
					array(
					'current_case' => $case_id,
				)
			);
			
		if ($smcFunc['db_num_rows']($request) == 0)
			fatal_lang_error('no_case', false);
		$row = $smcFunc['db_fetch_assoc']($request);
		$smcFunc['db_free_result']($request);
	}
	
	// Check the name and message and steps for Cases.
	if (!isset($_POST['name']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['name'])) === '')
		$post_errors[] = 'no_name';
	if (!isset($_POST['message']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['message']), ENT_QUOTES) === '')
		$post_errors[] = 'no_message';
	if (!empty($modSettings['max_messageLength']) && $smcFunc['strlen']($_POST['message']) > $modSettings['max_messageLength'])
		$post_errors[] = 'long_message';
	if (!isset($_POST['steps']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['steps']), ENT_QUOTES) === '')
		$post_errors[] = 'no_steps';
	if (!empty($modSettings['max_messageLength']) && $smcFunc['strlen']($_POST['steps']) > $modSettings['max_messageLength'])
		$post_errors[] = 'long_message';
	if (!isset($_POST['expected_result']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['expected_result']), ENT_QUOTES) === '')
		$post_errors[] = 'no_expected_result';
	if (!empty($modSettings['max_messageLength']) && $smcFunc['strlen']($_POST['expected_result']) > $modSettings['max_messageLength'])
		$post_errors[] = 'long_message';
	else
	{
		// Prepare the message and steps a bit for some additional testing.
		$_POST['message'] = $smcFunc['htmlspecialchars']($_POST['message'], ENT_QUOTES);
		$_POST['steps'] = $smcFunc['htmlspecialchars']($_POST['steps'], ENT_QUOTES);
		$_POST['expected_result'] = $smcFunc['htmlspecialchars']($_POST['expected_result'], ENT_QUOTES);
		
		// Let's see if there's still some content left without the tags.
		if ($smcFunc['htmltrim'](strip_tags(parse_bbc($_POST['message'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['message'], '[html]') === false))
			$post_errors[] = 'no_message';
		if ($smcFunc['htmltrim'](strip_tags(parse_bbc($_POST['steps'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['steps'], '[html]') === false))
			$post_errors[] = 'no_steps';
		if ($smcFunc['htmltrim'](strip_tags(parse_bbc($_POST['expected_result'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['expected_result'], '[html]') === false))
			$post_errors[] = 'no_expected_result';
	}

	// Any mistakes?
	if (!empty($post_errors))
	{
		loadLanguage('Errors');
		
		//Check message from cases
		$context['post_error'] = array('message' => array());
		foreach ($post_errors as $post_error)
		{
			$context['post_error'][$post_error] = true;
			if ($post_error == 'long_message')
				$txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);

			$context['post_error']['message'][] = $txt['error_' . $post_error];
		}
		
		//Check steps from cases
		$context['post_error'] = array('steps' => array());
		foreach ($post_errors as $post_error)
		{
			$context['post_error'][$post_error] = true;
			if ($post_error == 'long_message')
				$txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);

			$context['post_error']['steps'][] = $txt['error_' . $post_error];
		}
		
		//Check steps from cases
		$context['post_error'] = array('expected_result' => array());
		foreach ($post_errors as $post_error)
		{
			$context['post_error'][$post_error] = true;
			if ($post_error == 'long_message')
				$txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);

			$context['post_error']['expected_result'][] = $txt['error_' . $post_error];
		}
		$context['test_suite']['current_case'] = $case_id;
		return TS_EditCase();
	}

	// At about this point, we're posting and that's that.
	ignore_user_abort(true);
	@set_time_limit(300);

	// Add special html entities to the Test Case Name, username, email and expected result.
	$_POST['name'] = strtr($smcFunc['htmlspecialchars']($_POST['name']), array("\r" => '', "\n" => '', "\t" => ''));
	$poster_name = htmlspecialchars($user_info['username']);
	$poster_email = htmlspecialchars($user_info['email']);

	// At this point, we want to make sure the name isn't too long.
	if ($smcFunc['strlen']($_POST['name']) > 100)
		$_POST['name'] = $smcFunc['substr']($_POST['name'], 0, 100);	

	$caseOptions = array(
		'id' => empty($case_id) ? 0 : $case_id,
		'id_suite' => empty($suite_id) ? 0 : $suite_id,
		'case_name' => $_POST['name'],
		'description' => $_POST['message'],
		'steps' => $_POST['steps'],
		'expected_result' => $_POST['expected_result'],
	);
	$posterOptions = array(
			'id_assigned' =>  empty($id_assigned) ? 0 : $id_assigned,
);

	// Only consider marking as editing if they have edited the subject, message or icon.
	if ((isset($_POST['name']) && $_POST['name'] != $row['case_name']) || (isset($_POST['message']) && $_POST['message'] != $row['description']) || (isset($_POST['steps']) && $_POST['steps'] != $row['steps']) || (isset($_POST['expected_result']) && $_POST['expected_result'] != $row['expected_result']))
	{
			$caseOptions['modify_time'] = time();
			$caseOptions['modified_by'] = $user_info['name'];
	}
	TS_modifyCase($caseOptions, $posterOptions);

	// If we didn't change anything this time but had before put back the old info.
	if (!isset($caseOptions['modify_time']) && !empty($row['modified_time']))
	{
		$caseOptions['modify_time'] = $row['modified_time'];
		$caseOptions['modified_by'] = $row['modified_by'];
	}
	redirectexit('action=testsuite;case='. $case_id);
}

function TS_CaseValidator()
{
	global $context, $modSettings, $smcFunc, $txt, $sourcedir;
	
	// Creating Suite, nope, first we are going to check it :D
	if (isset($_POST['message']) || isset($_POST['steps']) || !empty($context['post_error']))
	{
		// Validate inputs.
		if (empty($context['post_error']))
		{
			if (htmltrim__recursive(htmlspecialchars__recursive($_REQUEST['name'])) == '')
				$context['post_error']['no_name'] = true;
			if (htmltrim__recursive(htmlspecialchars__recursive($_REQUEST['message'])) == '')
				$context['post_error']['no_message'] = true;
			if (htmltrim__recursive(htmlspecialchars__recursive($_REQUEST['steps'])) == '')
				$context['post_error']['no_steps'] = true;
			if (htmltrim__recursive(htmlspecialchars__recursive($_REQUEST['expected_result'])) == '')
				$context['post_error']['no_expected_result'] = true;
			if (!empty($modSettings['max_messageLength']) && ($smcFunc['strlen']($_REQUEST['message']) > $modSettings['max_messageLength'] || $smcFunc['strlen']($_REQUEST['steps']) > $modSettings['max_messageLength'] || $smcFunc['strlen']($_REQUEST['expected_result']) > $modSettings['max_messageLength']))
				$context['post_error']['long_message'] = true;
		}
		else
		{
			if (!isset($_REQUEST['name']))
				$_REQUEST['name'] = '';
			if (!isset($_REQUEST['message']))
				$_REQUEST['message'] = '';
			if (!isset($_REQUEST['steps']))
				$_REQUEST['steps'] = '';
			if (!isset($_REQUEST['expected_result']))
				$_REQUEST['expected_result'] = '';
		}

		// Set up the inputs for the form.
		$name = strtr($smcFunc['htmlspecialchars']($_REQUEST['name']), array("\r" => '', "\n" => '', "\t" => ''));
		$message = $smcFunc['htmlspecialchars']($_POST['message'], ENT_QUOTES);
		$step = $smcFunc['htmlspecialchars']($_REQUEST['steps'], ENT_QUOTES);
		$expected_result = $smcFunc['htmlspecialchars']($_REQUEST['expected_result'], ENT_QUOTES);

		// Make sure the name and expected result isn't too long - taking into account special characters.
		if ($smcFunc['strlen']($name) > 100)
			$name = $smcFunc['substr']($name, 0, 100);

		// Have we inadvertently trimmed off the name of useful information?
		if ($smcFunc['htmltrim']($name) === '')
			$context['post_error']['no_name'] = true;

		// Any errors occurred?
		if (!empty($context['post_error']))
		{
			loadLanguage('Errors');

			$context['error_type'] = 'minor';

			$context['post_error']['message'] = array();
			foreach ($context['post_error'] as $post_error => $dummy)
			{
				if ($post_error == 'message')
					continue;

				if ($post_error == 'long_message')
					$txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);

				$context['post_error']['message'][] = $txt['error_' . $post_error];

				$context['error_type'] = 'serious';
			}
		}

		$context['name'] = addcslashes($name, '"');
		$context['message'] = str_replace(array('"', '<', '>', '&nbsp;'), array('&quot;', '&lt;', '&gt;', ' '), $message);
		$context['steps'] = str_replace(array('"', '<', '>', '&nbsp;'), array('&quot;', '&lt;', '&gt;', ' '), $step);
		$context['expected_result'] = str_replace(array('"', '<', '>', '&nbsp;'), array('&quot;', '&lt;', '&gt;', ' '), $expected_result);
		if(!empty($id_assigned))
		$context['id_assigned'] = $id_assigned;
		
		// No check is needed, since nothing is really posted.
		checkSubmitOnce('free');
	}
}

function TS_PostRun()
{
	global $txt, $scripturl, $modSettings, $user_info, $context, $sourcedir, $smcFunc, $settings;

	require_once($sourcedir . '/Subs-SM-TestSuite.php');

	if (empty($context['post_errors']))
		$context['post_errors'] = array();
	
	$context['test_suite']['current_case'] = isset($_REQUEST['c']) ? (int) $_REQUEST['c'] : 0;
	
	if (empty($context['test_suite']['current_case']))
	{
		fatal_lang_error('ts_no_case');
	}
	
	// Project ID and Suite ID for the run are needed.
	$info = TS_loadCase($context['test_suite']['current_case'], false);

	// Permissions.
	if (!($context['user']['is_admin'] || TS_can_do('manage_all') ||
			TS_can_do('manage_project', $info['id_project']) || TS_can_do('manage_suite', $info['id_suite'])))
		fatal_lang_error('ts_cannot_permission_generic');

	
	$id_bug = isset($_REQUEST['id_bug']) ? (int) $_REQUEST['id_bug'] : 0;

	TS_RunValidator();
	
	// Set the destination action for submission.
	$context['destination'] = 'createRun2';
	$context['submit_label'] = $txt['submit'];

	// Create page titles and linktrees
	$context['page_title'] = $txt['submit_run_result'];
	$context['linktree'][] = array(
		'url' => $context['test_suite']['url'] . ';case='. $context['test_suite']['current_case'],
		'name' => $txt['case'],
		'extra_before' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><strong class="nav">' . $context['page_title'] . ' ( </strong></span>',
		'extra_after' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><strong class="nav"> )</strong></span>'
	);
		
	// Call Our Sub-Template.
	$context['sub_template'] = 'create_run';
	
	checkSubmitOnce('register');
}

function TS_PostRun2()
{
	global $txt, $modSettings, $sourcedir, $context, $scripturl, $user_info, $smcFunc;

	require_once($sourcedir . '/Subs-SM-TestSuite.php');
	
	$context['test_suite']['current_case'] = isset($_REQUEST['c']) ? (int) $_REQUEST['c'] : 0;
	
	// Project ID and Suite ID for the run are needed.
	$info = TS_loadCase($context['test_suite']['current_case'], false);

	// Permissions.
	if (!($context['user']['is_admin'] || TS_can_do('manage_all') ||
			TS_can_do('manage_project', $info['id_project']) || TS_can_do('manage_suite', $info['id_suite'])))
		fatal_lang_error('ts_cannot_permission_generic');
	
	// Are we hacking?
	if (empty($context['test_suite']['current_case']))
	{
		fatal_lang_error('ts_no_case');
	}
	
	$id_bug = isset($_REQUEST['id_bug']) ? (int) $_REQUEST['id_bug'] : 0;
	$case_id = $context['test_suite']['current_case'];
	// Prevent double submission of this form.
	checkSubmitOnce('check');

	// No errors as yet.
	$post_errors = array();

	// If the session has timed out, let the user re-submit their form.
	if (checkSession('createRun', '', false) != '')
		$post_errors[] = 'session_timeout';

	if($_POST['result'] == 'select')
			$post_errors[] = 'no_result';
	if (!isset($_POST['feedback']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['feedback']), ENT_QUOTES) === '')
		$post_errors[] = 'no_feedback';
	else
	{
		// Prepare the feedback a bit for some additional testing.
		$_POST['feedback'] = $smcFunc['htmlspecialchars']($_POST['feedback'], ENT_QUOTES);
	}
	
	// Any mistakes?
	if (!empty($post_errors))
	{
		loadLanguage('Errors');
		
		$context['post_error'] = array('feedback' => array());
		foreach ($post_errors as $post_error)
		{
			$context['post_error'][$post_error] = true;
			if ($post_error == 'long_feedback')
				$txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);

			$context['post_error']['feedback'][] = $txt['error_' . $post_error];
		}
		
		return TS_PostRun();
	}

	// At about this point, we're posting and that's that.
	ignore_user_abort(true);
	@set_time_limit(300);

	// Add special html entities to the Test Case Name, username, email and expected result.
	$poster_name = htmlspecialchars($user_info['username']);
	$poster_email = htmlspecialchars($user_info['email']);

	$runOption = array(
		'id' => 0,
		'id_case' => empty($case_id) ? 0 : $case_id,
		'result_achieved' => $_POST['result'],
		'feedback' => $_POST['feedback'],
		'id_bug' => empty($id_bug) ? 0 : $id_bug,
	);
	$posterOptions = array(
		'id' => $user_info['id'],
		'name' => $poster_name,
		'email' => $poster_email,
	);
	TS_createRun($runOption, $posterOptions);	
	$case = TS_loadCase($case_id);

	// Update the counter for total no of runs made in suites table
	$request = $smcFunc['db_query']('', '
			UPDATE {db_prefix}testsuite_suites
			SET count = count + {int:count}
			WHERE id_suite = {int:id_suite}',
				array(
					'id_suite' => $case['id_suite'],
					'count' => 1,
				)
	);
	$smcFunc['db_free_result']($request);
				
	// Update the counter for no. of fail runs made in suites table
	if($_POST['result'] == 'fail')
	{
		$request = $smcFunc['db_query']('', '
			UPDATE {db_prefix}testsuite_suites
			SET fail_count = fail_count + {int:fail_count}
			WHERE id_suite = {int:id_suite}',
				array(
					'id_suite' => $case['id_suite'],
					'fail_count' => 1,
			)
		);
		$smcFunc['db_free_result']($request);
	}

	// Update the counter for total no of runs made in cases table
	$request = $smcFunc['db_query']('', '
			UPDATE {db_prefix}testsuite_cases
			SET count = count + {int:count}
			WHERE id_case = {int:id_case}',
				array(
					'id_case' => $case_id,
					'count' => 1,
				)
	);
	$smcFunc['db_free_result']($request);
		
	// Update the counter for no. of fail runs made in cases table
	if($_POST['result'] == 'fail')
	{
		$request = $smcFunc['db_query']('', '
			UPDATE {db_prefix}testsuite_cases
			SET fail_count = fail_count + {int:fail_count}
			WHERE id_case = {int:id_case}',
				array(
					'id_case' => $case_id,
					'fail_count' => 1,
			)
		);
		$smcFunc['db_free_result']($request);
	}
  
	// Dut-dut-duh-duh-DUH-duh-dut-duh-duh!  *dances to the Final Fantasy Fanfare...*
	redirectexit('action=testsuite;case=' . $case_id);
}

function TS_EditRun()
{
	global $txt, $scripturl, $modSettings, $user_info, $context, $sourcedir, $smcFunc, $settings;

	if (empty($context['test_suite']['current_run']))
	$context['test_suite']['current_run'] = isset($_REQUEST['editrun']) ? (int) $_REQUEST['editrun'] : 0; 
	$run_id = $context['test_suite']['current_run'];
	if (empty($run_id))
	$run_id = isset($_REQUEST['r']) ? (int) $_REQUEST['r'] : 0;
	
	if(empty($run_id))
	return false;

	$id_bug = isset($_REQUEST['id_bug']) ? (int) $_REQUEST['id_bug'] : 0;

	require_once($sourcedir . '/Subs-SM-TestSuite.php');	
	
	// Get data for this specific suite.
	if(!empty($run_id))
	{
		$request = $smcFunc['db_query']('', '
				SELECT
					r.result_achieved, r.feedback, r.id_bug, r.id_member, r.poster_name, r.poster_time, r.poster_email, r.modified_by, r.modified_time, r.id_case
					FROM {db_prefix}testsuite_runs AS r
					WHERE r.id_run = {int:current_run}',
					array(
					'current_run' => $context['test_suite']['current_run'],
					'current_member' => $user_info['id'],
				)
			);
			
		if ($smcFunc['db_num_rows']($request) == 0)
			fatal_lang_error('ts_no_run', false);
		$row = $smcFunc['db_fetch_assoc']($request);

		$case_id = $row['id_case'];
		$context['result_achieved'] = $row['result_achieved'];
		$context['feedback'] = $row['feedback'];
		$context['id_bug'] = $row['id_bug'];
		
		$smcFunc['db_free_result']($request);

	}

	if (empty($context['post_errors']))
	    $context['post_errors'] = array();
		
	TS_RunValidator();

	// Set the destination action for submission.
	$context['destination'] = 'editrun2';
	$context['submit_label'] = $txt['submit'];

	// Call Our Sub-Template.
	$context['sub_template'] = 'edit_run';
	
	$context['page_title'] = $txt['edit'] . ' '. $txt['run'];
	
	$context['linktree'][] = array(
	'url' => $context['test_suite']['url'] . ';case=' . $case_id . '',
	'name' => $txt['case'],
	'extra_before' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><strong class="nav">' . $context['page_title'] . ' ( </strong></span>',
	'extra_after' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><strong class="nav"> )</strong></span>'
	);
}

function TS_EditRun2()
{
	global $txt, $modSettings, $sourcedir, $context, $scripturl, $user_info, $smcFunc;

	require_once($sourcedir . '/Subs-SM-TestSuite.php');
	
	$run_id = $context['test_suite']['current_run'];
	if (empty($run_id))
	$run_id = isset($_REQUEST['r']) ? (int) $_REQUEST['r'] : 0;
	
	$id_bug = isset($_REQUEST['id_bug']) ? (int) $_REQUEST['id_bug'] : 0;
	
	// Prevent double submission of this form.
	checkSubmitOnce('check');

	// No errors as yet.
	$post_errors = array();

	// If the session has timed out, let the user re-submit their form.
	if (checkSession('editrun', '', false) != '')
		$post_errors[] = 'session_timeout';

	// Get data for this specific run.
	$request = $smcFunc['db_query']('', '
				SELECT
					r.result_achieved, r.feedback, r.id_bug, r.id_member, r.poster_name, r.poster_time, r.poster_email, r.modified_by, r.modified_time, r.id_case
					FROM {db_prefix}testsuite_runs AS r
					WHERE r.id_run = {int:current_run}',
					array(
					'current_run' => $run_id,
					'current_member' => $user_info['id'],
				)
			);
			
		if ($smcFunc['db_num_rows']($request) == 0)
			fatal_lang_error('no_run', false);
		$row = $smcFunc['db_fetch_assoc']($request);
		$smcFunc['db_free_result']($request);		
		
	// If the session has timed out, let the user re-submit their form.
	if (checkSession('createRun', '', false) != '')
		$post_errors[] = 'session_timeout';

	if($_POST['result'] == 'select')
			$post_errors[] = 'no_result';
	if (!isset($_POST['feedback']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['feedback']), ENT_QUOTES) === '')
		$post_errors[] = 'no_feedback';
	else
	{
		// Prepare the feedback a bit for some additional testing.
		$_POST['feedback'] = $smcFunc['htmlspecialchars']($_POST['feedback'], ENT_QUOTES);
	}
	
	// Any mistakes?
	if (!empty($post_errors))
	{
		loadLanguage('Errors');
		
		$context['post_error'] = array('feedback' => array());
		foreach ($post_errors as $post_error)
		{
			$context['post_error'][$post_error] = true;
			if ($post_error == 'long_feedback')
				$txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);

			$context['post_error']['feedback'][] = $txt['error_' . $post_error];
		}
		$context['test_suite']['current_run'] = $run_id;
		return TS_EditRun();
	}

	// At about this point, we're posting and that's that.
	ignore_user_abort(true);
	@set_time_limit(300);

	// Add special html entities to the Test Case Name, username, email and expected result.
	$poster_name = htmlspecialchars($user_info['username']);
	$poster_email = htmlspecialchars($user_info['email']);

	$runOptions = array(
		'id' => empty($run_id) ? 0 : $run_id,
		'result_achieved' => $_POST['result'],
		'feedback' => $_POST['feedback'],
		'id_bug' => empty($id_bug) ? 0 : $id_bug,
	);
	$posterOptions = array();

	// Only consider marking as editing if they have edited the subject, message or icon.
	if ((isset($_POST['result']) && $_POST['result'] != $row['result_achieved']) || (isset($_POST['feedback']) && $_POST['feedback'] != $row['feedback']) || (isset($_POST['id_bug']) && $_POST['id_bug'] != $row['id_bug']))
	{
			$runOptions['modify_time'] = time();
			$runOptions['modified_by'] = $user_info['name'];
	}

	TS_modifyRun($runOptions, $posterOptions);

	// If we didn't change anything this time but had before put back the old info.
	if (!isset($runOptions['modify_time']) && !empty($row['modified_time']))
	{
		$runOptions['modify_time'] = $row['modified_time'];
		$runOptions['modified_by'] = $row['modified_by'];
	}

	redirectexit('action=testsuite;case='. $row['id_case']);
}

function TS_RunValidator()
{
	global $context, $modSettings, $smcFunc, $txt;

	if (isset($_POST['message']) || isset($_POST['feedback']))
	{
		// Validate inputs.
		if (empty($context['post_error']))
		{
			if($_POST['result'] == 'select')
				$context['post_error']['no_result'] = true;
			if (htmltrim__recursive(htmlspecialchars__recursive($_REQUEST['feedback'])) == '')
				$context['post_error']['no_feedback'] = true;
			if ($smcFunc['strlen']($_REQUEST['feedback']) > $modSettings['max_messageLength'])
				$context['post_error']['long_message'] = true;
		}
		else
		{
			if (!isset($_REQUEST['result']))
				$_REQUEST['result'] = '';
			if (!isset($_REQUEST['feedback']))
				$_REQUEST['feedback'] = '';
		}

		// Set up the inputs for the form.
		$feedback = $smcFunc['htmlspecialchars']($_REQUEST['feedback'], ENT_QUOTES);

		// Any errors occurred?
		if (!empty($context['post_error']))
		{
			loadLanguage('Errors');

			$context['error_type'] = 'minor';

			$context['post_error']['feedback'] = array();
			foreach ($context['post_error'] as $post_error => $dummy)
			{
				if ($post_error == 'feedback')
					continue;

				if ($post_error == 'long_message')
					$txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);

				$context['post_error']['feedback'][] = $txt['error_' . $post_error];

				$context['error_type'] = 'serious';
			}
		}
		
		$context['result_achieved'] = $_REQUEST['result'];
		$context['feedback'] = str_replace(array('"', '<', '>', '&nbsp;'), array('&quot;', '&lt;', '&gt;', ' '), $feedback);
	
		if(!empty($id_bug))
                    $context['id_bug'] = $id_bug;

		// No check is needed, since nothing is really posted.
		checkSubmitOnce('free');
	}
}

function TS_DeleteItem()
{
	global $sourcedir;

	isAllowedTo('admin_forum');
	$project_id = isset($_REQUEST['removeProject']) ? (int) $_REQUEST['removeProject'] : 0;
	$suite_id = isset($_REQUEST['removeSuite']) ? (int) $_REQUEST['removeSuite'] : 0;
	$case_id = isset($_REQUEST['removeCase']) ? (int) $_REQUEST['removeCase'] : 0;
	$run_id = isset($_REQUEST['removeRun']) ? (int) $_REQUEST['removeRun'] : 0;

	require_once($sourcedir . '/Subs-SM-TestSuite.php');
	if (!empty($project_id))
	{
		// Make sure the project exists first.
		$project = TS_loadProject($project_id);
		TS_removeProject($project_id);
		redirectexit('action=testsuite');
	}
	elseif (!empty($suite_id))
	{
		// So we can go back to where the suite was deleted and verify it exists.
		$suite = TS_loadSuite($suite_id);		
		$project_id = $suite['id_project'];

		TS_removeSuite($suite_id);
		redirectexit('action=testsuite;project=' . $project_id);
	}
	elseif (!empty($case_id))
	{
		$case = TS_loadCase($case_id);
		$suite_id = $case['id_suite'];
		
		TS_removeCase($case_id);
		redirectexit('action=testsuite;suite=' . $suite_id);
	}
	elseif (!empty($run_id))
	{
		$run = TS_loadRun($run_id);
		$case_id = $run['id_case'];
		TS_removeRun($run_id);
		redirectexit('action=testsuite;case=' . $case_id);
	}	
	
	// Should never get to here, but well, do it anyway!
	fatal_lang_error('ts_no_suite');
}

function TS_load_permissions()
{
	global $context, $sourcedir, $modSettings;

	// For version 1.0, the permissions are hardcoded and the file must be edited.
	// By default admins and global moderators can do everything.
	// Guests and Regular Members can view everything.
	$perms = array(
		// Guests and regular members.
		'view_all' => array(-1, 0),
		'submit_runs_all' => array(),
		// Test for whether the user belongs to a group that can submit runs for various test cases.
		'submit_runs_for_suite' => array(),
		'submit_runs_for_case' => array(),
		'submit_runs_for_project' => array(),
		// Manage permission includes: run creation/modification/deletion, suite and case creating/modifying/deleting/moving
		'manage_all' => array(),
		'manage_project' => array(),
		'manage_suite' => array(),
	);
		
	if (!empty($context['test_suite']['debug']))
	{
		// Because regular members can, that's why! Project #1 at least!
		$perms['manage_project'] = array(1 => array());
		$perms['manage_suite'] = array(2 => array(0));
	}
	
	// Like to save your changes in case this file gets updated/deleted?
	// If loading from file, change this to true or comment out the line.
	if (!empty($modSettings['ts_custom_permissions']))
	{
		include_once($sourcedir . '/TS_permissions.php');
		// Return your own custom $perms array in a func named getPermissions.
		$perms = getPermissions();
	}

	return $perms;
}

function TS_can_do($action, $secondary = 0)
{
	global $context, $user_info;
		
	// Grab the groups that can do...
	if (!empty($context['test_suite']['perms']))
	{
		// Is this a complex test?
		if (!empty($secondary))
		{
			if (isset($context['test_suite']['perms'][$action][$secondary]))
			{
				if (count(array_intersect($context['test_suite']['perms'][$action][$secondary], $user_info['groups'])) == 0)
					return false;
			}
			else
				return false;
		}
		
		elseif (count(array_intersect($context['test_suite']['perms'][$action], $user_info['groups'])) == 0)
		{
			return false;
		}
	}
	// Problem loading the permissions?
	else
	{
		return false;
	}
	
	return true;
}

?>